<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<style>
  body {
    background: #000;
  }

  #div1 {
    position: relative;
    width: 450px;
    height: 450px;
    margin: 20px auto 0;
  }

  #div1 a {
    position: absolute;
    top: 0;
    left: 0;
    font-family: Microsoft YaHei;
    color: #fff;
    font-weight: bold;
    text-decoration: none;
    padding: 3px 6px;
  }

  #div1 a:hover {
    border: 1px solid #eee;
    background: #000;
  }

  #div1 .blue {
    color: blue;
  }

  #div1 .red {
    color: red;
  }

  #div1 .yellow {
    color: yellow;
  }

  p {
    font: 16px Microsoft YaHei;
    text-align: center;
    color: #ba0c0c;
  }

  p a {
    font-size: 14px;
    color: #ba0c0c;
  }
  .sss{
    width: 30px;
    height: 30px;
    background-color: #18eeff;
  }
  p a:hover {
    color: red;
  }
</style>
<body>
<input type="checkbox">
<div id="div1">
  <a href="#">水果类别</a>
  <a href="#" class="red">苹果</a>
  <a href="#">香蕉</a>
  <a href="#">西瓜</a>
  <a href="#" class="blue">3Dtag</a>
  <a href="#">SEO</a>
  <a href="#">火龙果</a>
  <a href="#" class="yellow">梨</a>
  <a href="#" class="sss">球状</a>
  <a href="#" class="yellow">梨</a>
  <a href="#">球状</a>
  <a href="#" class="yellow">梨</a>
  <a href="#">球状</a>
  <a href="#" class="yellow">梨</a>
  <a href="#">球状</a>
  <a href="#" class="yellow">梨</a>
  <a href="#">球状</a>
  <a href="#" class="yellow">梨</a>
  <a href="#">球状</a>
  <a href="#" class="red">CSS</a>
  <a href="#">PHP</a>
  <a href="#" class="blue">Java</a>
  <a href="#">继承</a>
  <a href="#">C#</a>
  <a href="#" class="blue">OOP</a>
  <a href="#">语言类别</a>
  <a href="#" class="blue">西红柿</a>
  <a href="#">C++</a>
  <a href="#">C</a>
  <a href="#">番茄</a>
  <a href="#">demo</a>
</div>
<p>3D球状tag</p>
</body>
<script>
  var radius = 200; //旋转半径;
  var dtr = Math.PI / 180;
  var d = 600;

  var mcList = [];
  var active = false;
  var stop = false;
  var lasta = 1;
  var lastb = 1;
  var distr = true;
  var tspeed = 10;
  var size = 250;

  var mouseX = 0;
  var mouseY = 0;

  var howElliptical = 1;

  var aA = null;
  var oDiv = null;

  window.onload = function () {
    var i = 0;
    var oTag = null;

    oDiv = document.getElementById('div1');

    aA = oDiv.getElementsByTagName('a');

    for (i = 0; i < aA.length; i++) {
      oTag = {};

      oTag.offsetWidth = aA[i].offsetWidth;
      oTag.offsetHeight = aA[i].offsetHeight;
      aA[i].onmouseover = function (e) {
        e.stopPropagation();
        active = false;
        stop = true;
        console.log('onmouseover')
      }
      aA[i].onmousemove = function (e) {
        e.stopPropagation();
        active = false;
        stop = true;
        console.log('onmousemove')
      }
      mcList.push(oTag);
    }
    console.log(mcList)
    sineCosine(0, 0, 0);

    positionAll();

    oDiv.onmouseover = function () {
      active = true;
      stop = false;
      console.log('oDiv')
    };

    oDiv.onmouseout = function () {
      active = false;
      stop = false;
    };

    oDiv.onmousemove = function (ev) {
      var oEvent = window.event || ev;

      mouseX = oEvent.clientX - (oDiv.offsetLeft + oDiv.offsetWidth / 2);
      mouseY = oEvent.clientY - (oDiv.offsetTop + oDiv.offsetHeight / 2);

      mouseX /= 5;
      mouseY /= 5;
    };

    setInterval(update, 30);
  };

  function update() {
    var a;
    var b;

    if (active) {
      a = (-Math.min(Math.max(-mouseY, -size), size) / radius) * tspeed;
      b = (Math.min(Math.max(-mouseX, -size), size) / radius) * tspeed;
    }
    else {
      if (stop) {
        a = 0;
        b = 0;
      }else {
        a = lasta * 0.98;
        b = lastb * 0.98;
      }
    }

    lasta = a;
    lastb = b;

    if (Math.abs(a) <= 0.01 && Math.abs(b) <= 0.01) {
      return;
    }

    var c = 0;
    sineCosine(a, b, c);
    for (var j = 0; j < mcList.length; j++) {
      var rx1 = mcList[j].cx;
      var ry1 = mcList[j].cy * ca + mcList[j].cz * (-sa);
      var rz1 = mcList[j].cy * sa + mcList[j].cz * ca;

      var rx2 = rx1 * cb + rz1 * sb;
      var ry2 = ry1;
      var rz2 = rx1 * (-sb) + rz1 * cb;

      var rx3 = rx2 * cc + ry2 * (-sc);
      var ry3 = rx2 * sc + ry2 * cc;
      var rz3 = rz2;

      mcList[j].cx = rx3;
      mcList[j].cy = ry3;
      mcList[j].cz = rz3;

      per = d / (d + rz3);

      mcList[j].x = (howElliptical * rx3 * per) - (howElliptical * 2);
      mcList[j].y = ry3 * per;
      mcList[j].scale = per;
      mcList[j].alpha = per;

      mcList[j].alpha = (mcList[j].alpha - 0.6) * (10 / 6);
    }

    doPosition();
    depthSort();
  }

  function depthSort() {
    var i = 0;
    var aTmp = [];

    for (i = 0; i < aA.length; i++) {
      aTmp.push(aA[i]);
    }

    aTmp.sort
    (
      function (vItem1, vItem2) {
        if (vItem1.cz > vItem2.cz) {
          return -1;
        }
        else if (vItem1.cz < vItem2.cz) {
          return 1;
        }
        else {
          return 0;
        }
      }
    );

    for (i = 0; i < aTmp.length; i++) {
      aTmp[i].style.zIndex = i;
    }
  }

  function positionAll() {
    var phi = 0;
    var theta = 0;
    var max = mcList.length;
    var i = 0;

    var aTmp = [];
    var oFragment = document.createDocumentFragment();

//随机排序
    for (i = 0; i < aA.length; i++) {
      aTmp.push(aA[i]);
    }

    aTmp.sort
    (
      function () {
        return Math.random() < 0.5 ? 1 : -1;
      }
    );

    for (i = 0; i < aTmp.length; i++) {
      oFragment.appendChild(aTmp[i]);
    }

    oDiv.appendChild(oFragment);

    for (var i = 1; i < max + 1; i++) {
      if (distr) {
        phi = Math.acos(-1 + (2 * i - 1) / max);
        theta = Math.sqrt(max * Math.PI) * phi;
      }
      else {
        phi = Math.random() * (Math.PI);
        theta = Math.random() * (2 * Math.PI);
      }
//坐标变换
      mcList[i - 1].cx = radius * Math.cos(theta) * Math.sin(phi);
      mcList[i - 1].cy = radius * Math.sin(theta) * Math.sin(phi);
      mcList[i - 1].cz = radius * Math.cos(phi);

      aA[i - 1].style.left = mcList[i - 1].cx + oDiv.offsetWidth / 2 - mcList[i - 1].offsetWidth / 2 + 'px';
      aA[i - 1].style.top = mcList[i - 1].cy + oDiv.offsetHeight / 2 - mcList[i - 1].offsetHeight / 2 + 'px';
    }
  }

  function doPosition() {
    var l = oDiv.offsetWidth / 2;
    var t = oDiv.offsetHeight / 2;
    for (var i = 0; i < mcList.length; i++) {
      aA[i].style.left = mcList[i].cx + l - mcList[i].offsetWidth / 2 + 'px';
      aA[i].style.top = mcList[i].cy + t - mcList[i].offsetHeight / 2 + 'px';

      aA[i].style.fontSize = Math.ceil(12 * mcList[i].scale / 2) + 8 + 'px';

      aA[i].style.filter = "alpha(opacity=" + 100 * mcList[i].alpha + ")";
      aA[i].style.opacity = mcList[i].alpha;
    }
  }

  function sineCosine(a, b, c) {
    sa = Math.sin(a * dtr);
    ca = Math.cos(a * dtr);
    sb = Math.sin(b * dtr);
    cb = Math.cos(b * dtr);
    sc = Math.sin(c * dtr);
    cc = Math.cos(c * dtr);
  }
</script>
</html>
